package com.zxhhyj.storm.dsl

import com.zxhhyj.storm.schema.Column
import kotlin.jvm.JvmInline

@JvmInline
value class ConditionalExpression(val value: Type) {

    fun build(): String {
        return when (val type = value) {
            is Type.Eq -> {
                "${type.field} = '${type.value}'"
            }

            is Type.Neq -> {
                "${type.field} != '${type.value}'"
            }

            is Type.Gt -> {
                "${type.field} > '${type.value}'"
            }

            is Type.Lt -> {
                "${type.field} < '${type.value}'"
            }

            is Type.Like -> {
                "${type.field} LIKE '${type.pattern}'"
            }

            is Type.In -> {
                "${type.field} IN (${type.values.joinToString { it }})"
            }

            is Type.And -> {
                "(${type.front.build()} AND ${type.back.build()})"
            }

            is Type.Or -> {
                "(${type.front.build()} OR ${type.back.build()})"
            }
        }
    }

    sealed interface Type {
        // 等于：field = value
        data class Eq(val field: String, val value: String) : Type

        // 不等于：field != value
        data class Neq(val field: String, val value: String) : Type

        // 大于：field > value
        data class Gt(val field: String, val value: String) : Type

        // 小于：field < value
        data class Lt(val field: String, val value: String) : Type

        // 模糊匹配：field LIKE pattern
        data class Like(val field: String, val pattern: String) : Type

        // IN 查询：field IN (v1, v2, ...)
        data class In(val field: String, val values: List<String>) : Type

        // 逻辑与：条件1 AND 条件2 ...
        data class And(val front: ConditionalExpression, val back: ConditionalExpression) : Type

        // 逻辑或：条件1 OR 条件2 ...
        data class Or(val front: ConditionalExpression, val back: ConditionalExpression) : Type
    }

    companion object {

        infix fun Column<*, *>.eq(value: Column<*, *>): ConditionalExpression {
            return ConditionalExpression(Type.Eq(this.fieldName, value.fieldName))
        }

        infix fun <T> Column<*, T>.eq(value: T): ConditionalExpression {
            return ConditionalExpression(Type.Eq(this.fieldName, value.toString()))
        }

        infix fun Column<*, *>.neq(value: Column<*, *>): ConditionalExpression {
            return ConditionalExpression(Type.Neq(this.fieldName, value.fieldName))
        }

        infix fun <T> Column<*, T>.neq(value: T): ConditionalExpression {
            return ConditionalExpression(Type.Neq(this.fieldName, value.toString()))
        }

        infix fun ConditionalExpression.and(value: ConditionalExpression): ConditionalExpression {
            return ConditionalExpression(Type.And(this, value))
        }

        infix fun ConditionalExpression.or(value: ConditionalExpression): ConditionalExpression {
            return ConditionalExpression(Type.Or(this, value))
        }

    }

}